/*
 * Jenny Ruppen 09-730-391
 * Sebastien Goldberg 08-914-855
 * Henry Raymond 08-928-061
 * Stefan Mussato 09-752-270
 */
 
package ch.uzh.ifi.sopra.gruppe9.game;

import com.jme3.material.Material;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.util.BufferUtils;
import com.jme3.scene.VertexBuffer.Type;


/**
 * Draws a square in the GUI.
 */
public class GuiQuad extends Node {

	
	/**
	 * Offset of the coordinate system of this square.
	 */
	private GUI.Offset offset;
	
	
	/**
	 * Position of the square in the x axis. (Assuming the window has a width of 1024 pixel.)
	 */
	private float positionX;
	
	
	/**
	 * Position of the square in the y axis. (Assuming the window has a height of 768 pixel.)
	 */
	private float positionY;
	
	
	/**
	 * Width of the square. (Assuming the window has a width of 1024 pixel.)
	 */
	private float width;
	
	
	/**
	 * Height of the square. (Assuming the window has a height of 768 pixel.)
	 */
	private float height;
	
	
	/**
	 * Z-Index of the element. An element with a higher index will cover an element with a lower one.
	 */
	private float zIndex;
	
	
	/**
	 * Material of the square
	 */
	private Material material;
	
	
	/**
	 * Mesh of the square.
	 */
	private Mesh mesh;
	
	
	/**
	 * Geometry node of the square.
	 */
	private Geometry geometry;
	
	
	/**
	 * Texture coordinates.
	 */
	private Vector2f[] textureCoords;
	
	
	/**
	 * Constructor
	 */
	public GuiQuad() {
	}
	
	
	/**
	 * Sets position and size
	 */
	public void setPositionSize(GUI.Offset offset, int positionX, int positionY, int width, int height, int zIndex) {
		this.offset = offset;
		this.positionX = GUI.calculateX(this.offset, positionX);
		this.positionY = GUI.calculateY(this.offset, positionY);
		this.width = GUI.getPixelScale() * (float)width;
		this.height = GUI.getPixelScale() * (float)height;
		this.zIndex = (float)zIndex;
	}
	
	
	/**
	 * Sets position and size
	 */
	public void setAbsolutePositionSize(int positionX, int positionY, int width, int height, float zIndex) {
		this.offset = GUI.Offset.NONE;
		this.positionX = GUI.getPixelScale() * (float)positionX;
		this.positionY = -GUI.getPixelScale() * (float)positionY;
		this.width = GUI.getPixelScale() * (float)width;
		this.height = GUI.getPixelScale() * (float)height;
		this.zIndex = zIndex;
	}
	
	
	/**
	 * Sets material and texture coordinates
	 */
	public void setMaterial(Material material, float textureX, float textureY, float textureWidth, float textureHeight) {
		this.material = material;
		
        textureCoords = new Vector2f[4];
        textureCoords[0] = new Vector2f(textureX + 0,            (1.0f - (textureY + textureHeight)));
        textureCoords[1] = new Vector2f(textureX + textureWidth, (1.0f - (textureY + textureHeight)));
        textureCoords[2] = new Vector2f(textureX + 0,            (1.0f - (textureY + 0)));
        textureCoords[3] = new Vector2f(textureX + textureWidth, (1.0f - (textureY + 0)));
	}
	
	
	/**
	 * Creates mesh and geometry and returns element.
	 */
	public GuiQuad create() {		
		
		mesh = new Mesh();
        
        Vector3f[] vertices = new Vector3f[4];
        vertices[0] = new Vector3f(0, -1, 0);
        vertices[1] = new Vector3f(1, -1, 0);
        vertices[2] = new Vector3f(0, 0, 0);
        vertices[3] = new Vector3f(1, 0, 0);
 
        int[] indexes = {2, 0, 1, 1, 3, 2};
 
        mesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
        mesh.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(textureCoords));
        mesh.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indexes));
 
        geometry = new Geometry(name, mesh);
        
        geometry.setMaterial(this.material);
        
        geometry.setLocalScale(width, height, 1.0f);
        
        geometry.setLocalTranslation(positionX, positionY, zIndex);
        
        this.attachChild(geometry);
        
        return this;
	}


	/**
	 * Changes the texture coordinates for the square.
	 */
	public void changeTextureCoords(float textureX, float textureY, float textureWidth, float textureHeight) {
        textureCoords[0] = new Vector2f(textureX + 0,            (1.0f - (textureY + textureHeight)));
        textureCoords[1] = new Vector2f(textureX + textureWidth, (1.0f - (textureY + textureHeight)));
        textureCoords[2] = new Vector2f(textureX + 0,            (1.0f - (textureY + 0)));
        textureCoords[3] = new Vector2f(textureX + textureWidth, (1.0f - (textureY + 0)));
        mesh.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(textureCoords));
	}
	
	
	/**
	 * Move square to new coordinates.
	 */
	public void moveTo(GUI.Offset offset, int positionX, int positionY, int zIndex) {
		this.offset = offset;
		this.positionX = GUI.calculateX(this.offset, positionX);
		this.positionY = GUI.calculateY(this.offset, positionY);
		this.zIndex = (float)zIndex;
		geometry.setLocalTranslation(this.positionX, this.positionY, this.zIndex);
	}
}
